package m.appserver;

import com.alibaba.fastjson.JSONObject;
import io.netty.handler.codec.http.HttpMethod;
import m.common.action.Action;
import m.common.action.HtmlResult;
import m.common.action.VueResult;
import m.system.util.ActionUtil;
import m.system.util.ClassUtil;
import m.system.util.JSONMessage;

import java.lang.reflect.Method;
import java.util.Map;

public class ActionRedirect {
    /**
     * uriMethod  uri方法
     * action action类
     * method 执行action方法
     */
    public ActionRedirect(HttpMethod uriMethod,Class<? extends Action> action,String method){
        this.uriMethod=uriMethod;
        this.action=action;
        this.method=method;
        this.json=null;
    }
    /**
     * uriMethod  uri方法
     * action action类
     * method 执行action方法
     * json 附加参数
     */
    public ActionRedirect(HttpMethod uriMethod,Class<? extends Action> action,String method,JSONObject json){
        this.uriMethod=uriMethod;
        this.action=action;
        this.method=method;
        this.json=json;
    }
    /** 默认GET
     * action action类
     * method 执行action方法
     */
    public ActionRedirect(Class<? extends Action> action,String method){
        this(HttpMethod.GET,action,method);
    }
    /** 默认POST
     * action action类
     * method 执行action方法
     * json 附加参数
     */
    public ActionRedirect(Class<? extends Action> action,String method,JSONObject json){
        this(HttpMethod.POST,action,method,json);
    }
    /** 默认POST
     * action action类
     * method 执行action方法
     * json 附加参数
     */
    public ActionRedirect(Class<? extends Action> action, String method, JSONMessage json){
        this(HttpMethod.POST,action,method,json.toJSON());
    }
    /**
     * uriMethod  uri方法
     * action action类
     * method 执行action方法
     * json 附加参数
     */
    public ActionRedirect(HttpMethod uriMethod,Class<? extends Action> action,String method,JSONMessage json){
        this(uriMethod,action,method,json.toJSON());
    }

    /**
     * vueResult  VueResult
     */
    public ActionRedirect(VueResult vueResult){
        this.vueResult=vueResult;
    }
    /**
     * htmlResult  htmlResult
     */
    public ActionRedirect(HtmlResult htmlResult){
        this.htmlResult=htmlResult;
    }
    private HttpMethod uriMethod;
    private Class<? extends Action> action;
    private Action realAction;
    private String method;
    private JSONObject json;
    private VueResult vueResult;
    private HtmlResult htmlResult;
    private Class<?>[] params;
    protected Object toResult(RequestUtil reqUtil,ResponseUtil resUtil) throws Exception {
        //VueResult 构造的直接返回
        if(null!=this.vueResult) return this.vueResult;
        //htmlResult 构造的直接返回
        if(null!=this.htmlResult) return this.htmlResult;
        //其他构造
        if (null != this.json)
            ActionUtil.fillJSONObject(reqUtil.getRequestJson(), this.json);
        realAction = reqUtil.getRequestJson().toJavaObject(this.action);
        realAction.setRequest(reqUtil);
        realAction.setResponse(resUtil);
        realAction.setAuthorization(reqUtil.getHeader("Authorization"));
        //查找action定义的请求注解,并返回参数名称和类型map
        Map<String, Class<?>> paramTypeMap = ActionUtil.getRequestParamList(realAction.getClass(), this.method, this.uriMethod.name());
        this.params=paramTypeMap.values().toArray(new Class<?>[]{});
        realAction.setFileMap(reqUtil.getFiles());
        //执行action的方法-----------------------------------
        return ClassUtil.executeMethod(realAction, this.method, params, resUtil.toMethodParams(paramTypeMap, reqUtil.getRequestJson()));
    }
    protected String toResultType(){
        if(null!=this.vueResult) return VueResult.class.getName();
        if(null!=this.htmlResult) return HtmlResult.class.getName();
        Method m=ClassUtil.getDeclaredMethods(this.action,this.method,this.params);
        if(null!=m) {
            return m.getAnnotatedReturnType().getType().getTypeName();
        }
        return null;
    }
    protected Action getRealAction(){
        return realAction;
    }

    @Override
    public String toString() {
        if(null!=this.vueResult) return this.vueResult.outHtml();
        if(null!=this.htmlResult) return this.htmlResult.outHtml();
        else return this.action.getName()+"."+this.method;
    }
}
